package com.project.collectAPI.comm;


import com.project.collectAPI.entity.WxOrderPay;
import com.fasterxml.jackson.dataformat.xml.XmlMapper;

import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.security.KeyFactory;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.Signature;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.util.Base64;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;

public class WxPay {

    public static final String appid="wx896ca5a457ec03f6";
    public static final String appSectret="123renrenkan123renrenkan123renre";
    public static final String mchid="1642147341";
    public static final String notify_url="https://www.aigxy.com/orders/PayCallBack";
    public static final String schema = "WECHATPAY2-SHA256-RSA2048";
    public static final String httpurl = "/v3/certificates";
    public static final String certSerial="291B5AE8C845E23876CCF81E535DE71EDBF93860"; //证书串号 1892294F1109E4B9A00182D9B22C3287274EABBF
    public static final String privateKey="MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDHsT6DEE2wIDbJ5DkAWZTDlHzwGW0OOfVawlgPgV6BN2mEcjz7o7NkpVbR8PWAdfosftF6bNVllVkf7lj6RGCevbOl+Bbdk5yWRYu2k4PyR62XudIs2YQ2n4JNwe2oIRO+Llwd4XKG04DbRpPoHRI7eD1tuoMzAM4qNM8MnwyO4Zvdl/x+w9xYw1gi2mvNB5juX0LXLcMEmyTWGJOp8gRGdR2MHtTL3c0rz14CntzVMsDlBaxEdA8ME/crRQLtEp8afqYvrwYw5nTkZsAGYJF/xt1r7pMwD8ShzHmdDzsWFy+LLuB59aHBNjfhH6wc46f3s3LdfAZNB4f0/I4j7+f3AgMBAAECggEARWCl+EEEzKkUf+YDi8STs7N2CLC8u9GVFZgpohFvNPN8fGB4IXEJVXFADaZqlNvoM+dHfgIrzaQql7ZmQWTaMKx1qrbbstWi9G5rEN6FW/pdLDaJ970GezfFvKAgomYDhvJyXItED+WRgh0uK9lVyUWICgRfqquf9Pft61OiuEy6crBNKTrT6nx0aWjaKEis7iQs4xDftI2dduu/lv/hWgJgLa24oa94q4yvachXr7DnyV1ELwI8rSVXy7OP25iaxCTq3dAvzHqref72V+E901w2lT340syJkBmQyCeb4O4TS+S31WkXUp4SZVoEf3cPqQzzloQMF5EGA9jvqvPnuQKBgQDq4IiSSdWo0C8eEUm8k2ocnMT/XePu7NkeNvjeutaHKrm0UXPj6t6xElVPEmS/4nDlSOQyx5opA8aRZ295N8Y8iLCvchI9ThOcS1/KB2uQnOxCeke5MxdjiBDHTZd61egtnslxtsQOLiFGRArR/fbuO3IQMfDjePm2XbC2TjfsYwKBgQDZpqtIgSNY1d938TzQW5JuVYZ8drGhNjlLkjEMrhTuDJFeui4GFEx+aURTpwv3DsqiL+EOIg5rebyBSciRa1tba+3iM7wLrOJLgjWg1yvll31AllO0xnVYW3XdiHS55GS0B6Chy2y1UbJ/L2i6qu6USzJSygoiWWYeFL0rnD9YXQKBgDlOa0P2C9FSagyV/z2pYfx1K4N67v/+fcLnerUtNOZpwEGElhgH2Cmv5WyTek1u/EiVDkhtdumG6E3VxNb4ir9+Qk2sMVMP160MnuR2BwKTpvlZSGKhWpWIPz/BaLIpuqpW0aOTCibDjo7MTy+JHVRm4J+e770waQzbsx/n2bEtAoGBAMiXQuTfn6QP+JSiUFn3C02EpR2whqT9RHDRm0MEbWW3T4LuM9yGeLlIayBtpCleCILRfal42bFT0NeXGLJtLxVisyr2YyiffS/6IVLK/DntFBKieSLyhNOZ91bknC92vxjsrq5uvRGe6dMt7mebgaZKZ2bFrfFaUzMGChJXPkpBAoGBAONNMxvmn0WH9Pj9nhfBySb4SdpJP6f5RR0eXCQCqd28ANAY35uHKCTgAh6F9lTjSQAl5trHkT9bAmF/ZS3QwjpvWN7uz1RUabrLw0fWVEaxSnjOcEMJbgoURh5M5z3K8hfcfK9ZkMyh7DKRAHTU3E+sS0bovPI+yeZp7vD6h0gU";

    //JSAPI下单
    public static Map<String,Object> unifiedorder(int total,String openid, String orderNo, String description, HttpServletRequest request) throws Exception {
        String httpUrl="https://api.mch.weixin.qq.com/pay/unifiedorder"; //https://api.mch.weixin.qq.com/v3/pay/transactions/jsapi

        String ClientIP=IPUtils.getIpAddr(request);
        if(ClientIP.equals("0:0:0:0:0:0:0:1")){
            ClientIP="14.210.76.75";
        }

        //随机数
        String nonceStr=WxPay.getRandomString(16);

        //Post参数
        WxOrderPay wxOrderPay=new WxOrderPay();
        wxOrderPay.setOpenid(openid);
        wxOrderPay.setAppid(appid);
        wxOrderPay.setMch_id(mchid);
        wxOrderPay.setNonce_str(nonceStr);
        wxOrderPay.setTotal_fee(total);
        wxOrderPay.setBody(description);
        wxOrderPay.setOut_trade_no(orderNo);
        wxOrderPay.setNotify_url(notify_url);
        wxOrderPay.setSpbill_create_ip(ClientIP);
        wxOrderPay.setTrade_type("JSAPI");

        //签名
        Map<String,Object> map=new HashMap<String,Object>();
        map.put("openid",openid); //关键词
        map.put("appid",appid); //关键词
        map.put("mch_id",mchid); //关键词
        map.put("nonce_str",nonceStr);  //关键词
        map.put("body",description);  //关键词
        map.put("out_trade_no",orderNo);  //关键词
        map.put("total_fee",total);  //关键词
        map.put("spbill_create_ip",ClientIP);
        map.put("notify_url",notify_url);
        map.put("trade_type","JSAPI");

        Map<String,Object> sortmap=MapKeySort.MapKeySort(map);
        sortmap.put("key",WxPay.appSectret); //追加秘钥字段
        //String sortString=MapKeySort.getKeyAndValueStr(sortmap);
        String sortString="";
        System.out.println("签名"+sortString);
        //System.out.println();

        wxOrderPay.setSign(sortString); //设置签名


        XmlMapper xmlMapper = new XmlMapper();
        String xml = xmlMapper.writeValueAsString(wxOrderPay);
        System.out.println("xml字符串:"+xml);

        //JSONObject json=JSONObject.parseObject(JSON.toJSONString(wxOrderPay));
        //System.out.println("json下单数据:"+json);

        //String authorizationString=schema+" "+getAuthorization("POST", "/v3/pay/transactions/jsapi", json.toJSONString());
        //String result =WeChat.HttpPostJson(httpUrl,json,authorizationString); //HttpJson请求
        Map<String,Object> result =WeChat.HttpPostXML(httpUrl,xml); //HttpJson请求

        System.out.println("Wxpay下单结果："+result);
        return result.size()>0?result:null;
    }





    //获取平台证书
    public static R getCertList() throws Exception {
        String httpUrl="https://api.mch.weixin.qq.com/v3/certificates";
        //认证类型
        String schema = "WECHATPAY2-SHA256-RSA2048";
        String httpurl = "/v3/certificates";
        String httpAuthorization =schema+" "+getAuthorization("GET", httpurl, "");
        System.out.println("httpAuthorization==>"+httpAuthorization);
        String result =WeChat.HttpGet(httpUrl,httpAuthorization); //HttpJson请求
        System.out.println("获取列表请求结果:"+result);
        return R.ok("获取证书列表成功");
    }





    /**
     * 得到签名信息
     * @param method
     * @param url
     * @param body
     * @return
     * @throws Exception
     */
    public static String getAuthorization(String method, String url, String body) throws Exception {
        String nonceStr = getRandomString(16).toUpperCase(); //随机号码
        long timestamp = System.currentTimeMillis() / 1000;
        //获取签名串
        String message = buildMessage(method, url, timestamp, nonceStr, body);
        System.out.println("签名串："+message);
        //得到签名
        String signature = sign(message.getBytes("utf-8"));
        System.out.println("签名值："+signature);
        //五项签名信息，无顺序要求
        String httpAuthorization = "mchid=\"" + mchid + "\","
                + "nonce_str=\"" + nonceStr + "\","
                + "signature=\"" + signature + "\","
                + "timestamp=\"" + timestamp + "\","
                + "serial_no=\"" + certSerial + "\""
                ;
        System.out.println("httpAuthorization:" + httpAuthorization);
        return httpAuthorization;
    }

    /**
     * 获取签名值
     * @param message
     * @return
     * @throws Exception
     */
    public static String sign(byte[] message) throws Exception {
        //signType	String	是	签名类型，默认为MD5，支持HMAC-SHA256和MD5。注意此处需与统一下单的签名类型一致
        Signature sign = Signature.getInstance("SHA256withRSA"); //SHA256withRSA
        //# 示例：私钥存储在文件
        //PrivateKey merchantPrivateKey = PemUtil.loadPrivateKey(new FileInputStream("D:\\test\\apiclient_key.pem"));
        PrivateKey merchantPrivateKey = getPrivateKey(privateKey);
        sign.initSign(merchantPrivateKey);
        sign.update(message);
        return Base64.getEncoder().encodeToString(sign.sign());
    }


    /**
     * 获取私钥。
     * @param filename 私钥文件路径  (required)
     * @return 私钥对象
     */
    public static PrivateKey getPrivateKey(String pkey) throws IOException {
        //String content = new String(Files.readAllBytes(pkey), "utf-8");
        String content =pkey;
        try {
            String privateKey = content.replace("-----BEGIN PRIVATE KEY-----", "")
                    .replace("-----END PRIVATE KEY-----", "")
                    .replaceAll("\\s+", "");
            KeyFactory kf = KeyFactory.getInstance("RSA");
            return kf.generatePrivate(
                    new PKCS8EncodedKeySpec(Base64.getDecoder().decode(privateKey)));
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException("当前Java环境不支持RSA", e);
        } catch (InvalidKeySpecException e) {
            throw new RuntimeException("无效的密钥格式");
        }
    }


    /**
     * 构造签名串
     * 签名串一共有五行，每一行为一个参数。行尾以 \n（换行符，ASCII编码值为0x0A）结束，包括最后一行。如果参数本身以\n结束，也需要附加一个\n
     * HTTP请求方法\n
     * URL\n
     * 请求时间戳\n
     * 请求随机串\n
     * 请求报文主体\n
     * @param method
     * @param url
     * @param timestamp
     * @param nonceStr
     * @param body
     * @return
     * @throws Exception
     */
    public static String buildMessage(String method, String url, long timestamp, String nonceStr, String body) {
        return method + "\n"
                + url + "\n"
                + timestamp + "\n"
                + nonceStr + "\n"
                + body + "\n";
    }


    public static String getRandomString(int length){
        String str="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
        Random random=new Random();
        StringBuffer sb=new StringBuffer();
        for(int i=0;i<length;i++){
            int number=random.nextInt(62);
            sb.append(str.charAt(number));
        }
        return sb.toString();
    }


} // class end
